// ============================================================================
// gzstream, C++ iostream classes wrapping the zlib compression library.
// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// ============================================================================
//
// File          : gzstream.h
// Revision      : $Revision: 1.1 $
// Revision_date : $Date: 2005/05/25 18:20:56 $
// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
// 
// Standard streambuf implementation following Nicolai Josuttis, "The 
// Standard C++ Library".
// ============================================================================

//    Changes by stephan@s11n.net:
//    October, 2003:
//    - added zlevel() to gzstreambase and gzstreambuf. Only works for ostreams.

#ifndef zfstream_GZSTREAM_H_INCLUDED
#define zfstream_GZSTREAM_H_INCLUDED 1


// standard C++ with new header file names and std:: namespace
#include <iostream>
#include <fstream>
#include <zlib.h>

namespace zfstream
{

// ----------------------------------------------------------------------------
// Internal classes to implement gzstream. See below for user classes.
// ----------------------------------------------------------------------------
	class gzstreambuf:public std::streambuf
	{
	      private:
		static const int bufferSize = 47 + 256;	// size of data buff
		// totals 512 bytes under g++ for igzstream at the end.

		gzFile file;	// file handle for compressed file
		char buffer[bufferSize];	// data buffer
		char opened;	// open/close state of stream
		int mode;	// I/O mode

		int flush_buffer();
	      public:
                gzstreambuf():opened( 0 ), m_zlevel(-1)
		{
			setp( buffer, buffer + ( bufferSize - 1 ) );
			setg( buffer + 4,	// beginning of putback area
			      buffer + 4,	// read position
			      buffer + 4 );	// end position      
			// ASSERT: both input & output capabilities will not be used together
		}
		int is_open()
		{
			return opened;
		}
		gzstreambuf *open( const char *name, int open_mode );
		gzstreambuf *close();
		~gzstreambuf()
		{
			close();
		}

		virtual int overflow( int c = EOF );
		virtual int underflow();
		virtual int sync();

                void zlevel( int z ) { this->m_zlevel = ( z<0 ? -1 : (z>9?9:z) ) ; }
                int zlevel() const  { return this->m_zlevel; }
        private:
                int m_zlevel;
	};

        /**
           Base stream class inherited by ogzstream/igzstream. Any
           given instance may not be used for both input and output.

           Uses gzlib compression, and is compatible with files compressed
           using gzip, or any number of other tools which support gzlib.

        */
	class gzstreambase:virtual public std::ios
	{
        private:
                int m_zlevel;
	      protected:
		gzstreambuf buf;
	      public:
		gzstreambase()
		{
			init( &buf );
		}
		gzstreambase( const char *name, int open_mode );
		~gzstreambase();
		void open( const char *name, int open_mode );
		void close();

                void zlevel( int z ) { buf.zlevel(z); }
                int zlevel() const  { return buf.zlevel(); }

		gzstreambuf *rdbuf()
		{
			return &buf;
		}
	};


        /**
           An input stream which decompresses it's input. Used
           identically to a std::ifstream.

<pre>
igzstream ifs( "myfile.gz" );
</pre>
        */
	class igzstream:public gzstreambase, public std::istream
	{
	      public:
		igzstream():std::istream( &buf )
		{
		}
	      igzstream( const char *name, int open_mode = std::ios::in ):gzstreambase( name, open_mode ), std::istream( &buf )
		{
		}
		gzstreambuf *rdbuf()
		{
			return gzstreambase::rdbuf();
		}
		void open( const char *name, int open_mode = std::ios::in )
		{
			gzstreambase::open( name, open_mode );
		}
	};

        /**
           An output stream which compresses it's output. Used identically to a std::ofstream:

<pre>
ogzstream of( "myfile.gz" );
of << "hello, world!" << std::endl;
</pre>
        */
	class ogzstream:public gzstreambase, public std::ostream
	{
	      public:
		ogzstream():std::ostream( &buf )
		{
		}
	      ogzstream( const char *name, int mode = std::ios::out ):gzstreambase( name, mode ), std::ostream( &buf )
		{
		}
		gzstreambuf *rdbuf()
		{
			return gzstreambase::rdbuf();
		}
		void open( const char *name, int open_mode = std::ios::out )
		{
			gzstreambase::open( name, open_mode );
		}
	};

}				// namespace

#endif // zfstream_GZSTREAM_H_INCLUDED
// ============================================================================
// EOF //
